package com.yunpeng.aidevice.biz.service.impl;

import com.yunpeng.aidevice.biz.service.IOrganizationBizService;
import com.yunpeng.common.dto.Result;
import com.yunpeng.aidevice.common.dto.save.OrgSaveDTO;
import com.yunpeng.aidevice.common.enums.ResultCodeEnum;
import com.yunpeng.aidevice.common.vo.SimpleEntityVO;
import com.yunpeng.aidevice.common.vo.org.OrganizationNodeVO;
import com.yunpeng.aidevice.common.vo.org.OrganizationRootVO;
import com.yunpeng.aidevice.common.vo.org.OrganizationVO;
import com.yunpeng.aidevice.dao.constant.DictionariesConstant;
import com.yunpeng.aidevice.dao.model.entity.OrganizationDO;
import com.yunpeng.aidevice.dao.model.entity.UserDO;
import com.yunpeng.aidevice.dao.service.IOrganizationService;
import com.yunpeng.aidevice.dao.service.IUserService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * OrganizationBizServiceImpl 组织机构业务服务实现
 *
 * @author : Moore(hemw)
 * @date : 2020-04-08
 */
@Service
public class OrganizationBizServiceImpl implements IOrganizationBizService {

    /**
     * 日志对象
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(OrganizationBizServiceImpl.class);


    @Resource
    private IOrganizationService organizationService;

    @Resource
    private IUserService userService;

    @Override
    /**
     * 获取用户归属的顶级组织节点信息
     *
     * @param userCode             用户代码
     * @param merchantCode         商户代码
     * @param userOrganizationPath 用户归属的组织路径
     * @return
     */
    public Result<OrganizationRootVO> getRoot(String userCode, String merchantCode, String userOrganizationPath) {
        OrganizationDO rootNode = organizationService.getRoot(userOrganizationPath, merchantCode, DictionariesConstant.INSTANCE.getDefaultTenantCode());
        if (rootNode == null) {
            LOGGER.error("get root error , access user {}", userCode);
            return Result.fail(ResultCodeEnum.DATA_ACCESS_FAIL);
        }
        OrganizationRootVO rootVO = new OrganizationRootVO(rootNode.getName(), rootNode.getCode(), rootNode.getNumber());
        return Result.success(rootVO);
    }


    @Override
    /**
     * 新增组织机构节点
     *
     * @param orgSaveDTO           节点保存信息
     * @param operatorCode         操作人代码
     * @return
     */
    public Result<String> addNew(OrgSaveDTO orgSaveDTO, String operatorCode) {
        OrganizationDO parentNode = null;
        if (StringUtils.isNotBlank(orgSaveDTO.getParentCode())) {
            parentNode = organizationService.getByCode(orgSaveDTO.getParentCode(), orgSaveDTO.getMerchantCode(), DictionariesConstant.INSTANCE.getDefaultTenantCode());
        } else if (StringUtils.isNotBlank(orgSaveDTO.getNumber())) {
            parentNode = organizationService.getByNumber(orgSaveDTO.getNumber(), orgSaveDTO.getMerchantCode(), DictionariesConstant.INSTANCE.getDefaultTenantCode());
        }

        if (parentNode != null) {
            orgSaveDTO.setParentCode(parentNode.getCode());
            orgSaveDTO.setParentNumber(parentNode.getNumber());
        }
        String orgCode = organizationService.addNewNode(orgSaveDTO, operatorCode, parentNode);
        if (StringUtils.isNotBlank(orgCode)) {
            return Result.success(orgCode);
        }
        return Result.fail(ResultCodeEnum.SAVE_DATA_FAILED);
    }

    @Override
    /**
     * 获取指定节点的树结构（本身和下级）
     *
     * @param nodeCode     节点代码
     * @param merchantCode 商户代码
     * @return
     */
    public Result<OrganizationNodeVO> getOrganizationTree(String nodeCode, String merchantCode) {
        OrganizationDO rootNode = organizationService.getByCode(nodeCode, merchantCode, DictionariesConstant.INSTANCE.getDefaultTenantCode());
        if (rootNode == null) {
            LOGGER.error("get node error , node not exists {}", nodeCode);
            return Result.build(ResultCodeEnum.NOT_EXISTS_DATA_FAILED.getValue(), "无此组织");
        }
        List<OrganizationDO> organizationDOList = organizationService.queryNodeListByPath(rootNode.getNodePath(), true, merchantCode, DictionariesConstant.INSTANCE.getDefaultTenantCode());
        if (organizationDOList == null || organizationDOList.isEmpty()) {
            LOGGER.error("query organization list error , node path {}", rootNode.getNodePath());
            return Result.fail(ResultCodeEnum.HAS_NOT_DATA_BIND);
        }
        OrganizationNodeVO parentVO = new OrganizationNodeVO();
        parentVO.setCode(rootNode.getCode());
        parentVO.setName(rootNode.getName());
        parentVO.setParentCode(rootNode.getParentCode());
        parentVO.setNumber(rootNode.getNumber());
        parentVO.setChildNode(processTree(rootNode.getCode(), organizationDOList));
        return Result.success(parentVO);
    }

    @Override
    /**
     * 删除组织
     *
     * @param nodeCode 组织机构代码
     * @param merchantCode 商户代码
     * @return
     * @return
     */
    public Result<Void> removeOrganization(String nodeCode, String merchantCode) {
        OrganizationDO rootNode = organizationService.getByCode(nodeCode, merchantCode, DictionariesConstant.INSTANCE.getDefaultTenantCode());
        if (rootNode == null) {
            LOGGER.error("get node error , node not exists {}", nodeCode);
            return Result.build(ResultCodeEnum.NOT_EXISTS_DATA_FAILED.getValue(), "无此组织");
        }
        StringBuilder reasonBuild = new StringBuilder();
        boolean countDeleted = true;
        //验证是否存在下级组织
        List<OrganizationDO> organizationDOList = organizationService.queryNodeListByPath(rootNode.getNodePath(), false, merchantCode, DictionariesConstant.INSTANCE.getDefaultTenantCode());
        if (organizationDOList != null && !organizationDOList.isEmpty()) {
            reasonBuild.append("存在下级组织,请先删除下级组织！");
            countDeleted = false;
        }
        //验证是否存在用户
        List<UserDO> userDOList = userService.queryListByOrganization(nodeCode);
        if (userDOList != null && !userDOList.isEmpty()) {
            reasonBuild.append("存在绑定用户,请先清理绑定关系！");
            countDeleted = false;
        }
        if (countDeleted) {
            if (organizationService.removeOrganizationNode(nodeCode)) {
                return Result.success();
            }
            return Result.fail(ResultCodeEnum.REMOVE_FAILED);
        }
        return Result.build(ResultCodeEnum.REMOVE_FAILED.getValue(), reasonBuild.toString());
    }

    @Override
    /**
     * 禁用组织（及其下级组织）
     *
     * @param nodeCode     组织代码
     * @param merchantCode 商户代码
     * @param operatorCode 操作人代码
     * @return
     */
    public Result<Void> disableOrganization(String nodeCode, String merchantCode, String operatorCode) {
        if (organizationService.disable(operatorCode, merchantCode, DictionariesConstant.INSTANCE.getDefaultTenantCode(), nodeCode)) {
            return Result.success();
        }
        return Result.fail(ResultCodeEnum.SAVE_DATA_FAILED);
    }

    @Override
    /**
     * 启用组织（及其下级组织）
     *
     * @param nodeCode     组织代码
     * @param merchantCode 商户代码
     * @param operatorCode 操作人代码
     * @return
     */
    public Result<Void> enableOrganization(String nodeCode, String merchantCode, String operatorCode) {
        if (organizationService.enable(operatorCode, merchantCode, DictionariesConstant.INSTANCE.getDefaultTenantCode(), nodeCode)) {
            return Result.success();
        }
        return Result.fail(ResultCodeEnum.SAVE_DATA_FAILED);
    }

    @Override
    /**
     * 更新组织机构
     *
     * @param orgSaveDTO   组织保存信息
     * @param operatorCode 操作人代码
     * @return
     */
    public Result<Void> updateOrganization(OrgSaveDTO orgSaveDTO, String operatorCode) {
        OrganizationDO parentNode = null;
        if (StringUtils.isNotBlank(orgSaveDTO.getParentCode())) {
            parentNode = organizationService.getByCode(orgSaveDTO.getParentCode(), orgSaveDTO.getMerchantCode(), DictionariesConstant.INSTANCE.getDefaultTenantCode());
        } else if (StringUtils.isNotBlank(orgSaveDTO.getNumber())) {
            parentNode = organizationService.getByNumber(orgSaveDTO.getNumber(), orgSaveDTO.getMerchantCode(), DictionariesConstant.INSTANCE.getDefaultTenantCode());
        }
        if (parentNode != null) {
            orgSaveDTO.setParentCode(parentNode.getCode());
            orgSaveDTO.setParentNumber(parentNode.getNumber());
        }
        if (organizationService.updateOrganization(orgSaveDTO, operatorCode, parentNode)) {
            return Result.success();
        }
        return Result.fail(ResultCodeEnum.SAVE_DATA_FAILED);
    }

    @Override
    /**
     * 获取组织详情
     *
     * @param organizationCode 组织机构代码
     * @param merchantCode     商户代码
     * @return
     */
    public Result<OrganizationVO> getOrganizationDetail(String organizationCode, String merchantCode) {
        OrganizationDO organizationDO = organizationService.getByCode(organizationCode, merchantCode, DictionariesConstant.INSTANCE.getDefaultTenantCode());
        if (organizationDO == null) {
            return Result.build(ResultCodeEnum.NOT_EXISTS_DATA_FAILED.getValue(), "无此组织");
        }
        OrganizationVO orgVo = new OrganizationVO();
        orgVo.setName(organizationDO.getName());
        orgVo.setCode(organizationDO.getCode());
        orgVo.setNodePath(organizationDO.getNodePath());
        orgVo.setPathName(organizationDO.getPathName());
        orgVo.setDisabled(organizationDO.getDisabled());
        orgVo.setNumber(organizationDO.getNumber());
        return Result.success(orgVo);
    }


    @Override
    /**
     * 组织机构下拉数据
     *
     * @param merchantCode
     * @param tenantCode
     * @return
     */
    public Result<List<SimpleEntityVO>> dropDownList(String merchantCode, String tenantCode) {
        List<OrganizationDO> organizationDOList = organizationService.getAllMerchantOrgList(merchantCode, tenantCode);
        if (organizationDOList == null || organizationDOList.isEmpty()) {
            return Result.success(new ArrayList<>());
        }
        return Result.success(organizationDOList.stream().map(t -> new SimpleEntityVO(t.getCode(), t.getNumber(), t.getNumber())).collect(Collectors.toList()));
    }

    //region 私有方法

    /**
     * 构造树
     *
     * @param parentCode         父节点代码
     * @param organizationDOList 数据集合
     * @return
     */
    private List<OrganizationNodeVO> processTree(String parentCode, List<OrganizationDO> organizationDOList) {
        List<OrganizationDO> subList = new ArrayList<>();
        List<OrganizationDO> anotherList = new ArrayList<>();
        for (OrganizationDO organizationDO : organizationDOList) {
            if (parentCode.equalsIgnoreCase(organizationDO.getParentCode())) {
                subList.add(organizationDO);
            } else {
                anotherList.add(organizationDO);
            }
        }
        List<OrganizationNodeVO> resultList = new ArrayList<>();
        for (OrganizationDO organizationDO : subList) {
            OrganizationNodeVO organizationNodeVO = new OrganizationNodeVO();
            organizationNodeVO.setCode(organizationDO.getCode());
            organizationNodeVO.setName(organizationDO.getName());
            organizationNodeVO.setParentCode(parentCode);
            organizationNodeVO.setNumber(organizationDO.getNumber());
            organizationNodeVO.setChildNode(processTree(organizationDO.getCode(), anotherList));
            resultList.add(organizationNodeVO);
        }
        return resultList;
    }

    //endregion
}
